#pragma once
#include "oglviewinterfaces.h"

#include "polynomial.h"

#include "ScreenRayPicker.h"

#define MAX_SPLINE_EDIT_PTS 20

class SplinePolySemantics
{
public:
	virtual void SetCurve(int, int, double *, double *, SplineEditCurve &) const =0;
};

namespace SplineHelpers
{
	SplinePolySemantics & GetLinearInterpolator();
	SplinePolySemantics & GetCubicInterpolator();
}

class SplineEditor :
	public ICustomDraw, public ICustomOnMouse
{
	int m_nPtsUsed;
	double m_arrLfSegPositions[MAX_SPLINE_EDIT_PTS];
	double m_arrLfSegHeights[MAX_SPLINE_EDIT_PTS];
	SplineEditCurve m_arrPolynomials[MAX_SPLINE_EDIT_PTS];

	SplinePolySemantics * m_pSemantics;

	bool m_bFunctionsValid;

	void ValidateFunctions();

	viewInfo m_viewInfoInternal;
	viewInfo m_viewInfoExposed;

	mdsVector<3, double> m_vecColor;

	double m_lfAspect;

	const ScreenRayPicker * m_pRayPicker;

	struct MouseInfo
	{
		bool m_bLastMouseValid;
		int m_nVertSelected;

		double m_lfPointSelectFuzz;

		mdsVector<2, double> m_p2LastMousePos;
		MouseInfo():m_bLastMouseValid(false),m_nVertSelected(-1),m_lfPointSelectFuzz(0.05) {}
	};

	ICustomCallback * m_pCallback;

	MouseInfo m_mouseInfo;
public:
	SplineEditor(void);
	virtual ~SplineEditor(void);

	virtual void Draw();

	void SetCallback(ICustomCallback * pCallback) { m_pCallback = pCallback; }

	void SetRayPicker(const ScreenRayPicker & rayPicker) {m_pRayPicker = &rayPicker;}

	void SetAspect(double lfAspect) {m_lfAspect = lfAspect; }
	double GetAspect() const { return m_lfAspect; }

	virtual bool OnMouseMove(UINT nFlags, double lfX, double lfY );

	int FindNextPoint(double lfPos) const;
	int InsertPt(double lfNewPos, double lfHeight);
	int DeletePt(int nIdxPt);

	viewInfo & GetViewInfo() 
	{
		m_viewInfoExposed = m_viewInfoInternal;
		return m_viewInfoExposed;
	}

	void SetDrawColor(double lfRed, double lfGreen, double lfBlue)
	{
		m_vecColor[0] = lfRed; m_vecColor[1] = lfGreen; m_vecColor[2] = lfBlue;
	}

	void SetDrawColor(const mdsVector<3, double> vecColor)
	{
		m_vecColor = vecColor;
	}

	void SetSplineSemantics(SplinePolySemantics * pSemantics) { m_pSemantics = pSemantics; } 
	// caller should manage memory, not class.

	void SetFinalPtHeight(double lfHeight)
	{
		m_arrLfSegHeights[m_nPtsUsed-1] = lfHeight;
	}

	SplineEditCurve * GetCurves() { return m_arrPolynomials; }
	double * GetKnots() { return m_arrLfSegPositions; } // messy YUCK

	int GetNumPts() const { return m_nPtsUsed; }
};
